﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using SharedGenomics.TextMining;
using SharedGenomics.Domain;

namespace SharedGenomics.Workbench.Views.WindowsForms
{
    public partial class MinedPublicationDisplayControl : UserControl
    {
        #region Private Members

        private PublicationMining _mining;
        private bool _detailsVisible;
        private Color[] _termQuartileColours;

        #endregion

        #region Constructors

        public MinedPublicationDisplayControl(PublicationMining mining, Color[] termQuartileColours)
        {
            InitializeComponent();

            this.Mining = mining;
            this.TermQuartileColours = termQuartileColours;
        }

        #endregion

        #region Event Handlers

        private void UserControl_Load(object sender, EventArgs e)
        {
            Publication pub = this.Mining.Pub;
            this.txtAbstract.Text = pub.Abstract;
            this.txtAuthors.Text = pub.Author;

            //hide details initially
            //NOTE: this is done here since it makes the Form Designer easier to use when the details panel isn't collapsed...
            this.DetailsVisible = false;
        }

        private void lbPublicationTitle_Paint(object sender, PaintEventArgs e)
        {
            float yPos = 0.0f;
            float xPos = 0.0f;                   //current position to draw the next tile section text onto the label

            Graphics g = e.Graphics;
            Label l = (Label)sender;
            Font sectionFont;
            Brush sectionBrush;

            g.Clear(l.BackColor);

            //add journal title
            Font journalFont = new Font(l.Font, FontStyle.Italic);
            Brush journalBrush = new SolidBrush(Color.Black);
            string journalString = String.Format("{0}: ", this.Mining.Pub.JournalName);

            //get the bounding rectangle of the journal title and fill the area in a light grey colour to increase the visual separation between the journal 
            //name and the publication title
            SizeF journalStringBounds = g.MeasureString(journalString, journalFont);
            Rectangle fillRect = new Rectangle(new Point((int)xPos, (int)yPos), Size.Truncate(journalStringBounds));
            g.FillRectangle(new SolidBrush(Color.FromArgb(230, 230, 230)), fillRect);

            //draw journal title
            g.DrawString(journalString, journalFont, journalBrush, xPos, yPos);
            xPos += journalStringBounds.Width;

            //draw each of the TileSections that comprise the publication title on the label
            foreach (TileSection ts in this.Mining.TitleMining)
            {
                //get font and brush to display current section
                this.GetFontAndBrushForTileSection(ts, out sectionFont, out sectionBrush);

                //draw string and then get the width and advance the drawing position of the next section
                g.DrawString(ts.Text, sectionFont, sectionBrush, xPos, yPos);
                xPos += g.MeasureString(ts.Text, sectionFont).Width;
            }

            //change width of label to fit the text
            l.Width = (int)Math.Ceiling(xPos);

            //if the label is now too big to fit in the control, increase the control width
            int requiredClientWidth = l.Location.X + l.Width;
            if (requiredClientWidth > this.ClientSize.Width)
            {
                this.Width = requiredClientWidth;
            }
        }

        private void llbUri_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start(this.Mining.Pub.Uri.ToString());
        }

        private void plHeader_MouseEnter(object sender, EventArgs e)
        {
            this.SetHighlighted(true);
        }

        private void plHeader_MouseLeave(object sender, EventArgs e)
        {
            this.SetHighlighted(false);
        }

        private void plHeader_Click(object sender, EventArgs e)
        {
            this.DetailsVisible = !this.DetailsVisible;
        }

        private void lbPublicationTitle_Click(object sender, EventArgs e)
        {
            this.DetailsVisible = !this.DetailsVisible;
        }

        private void lbPublicationTitle_MouseEnter(object sender, EventArgs e)
        {
            this.SetHighlighted(true);
        }

        private void lbPublicationTitle_MouseLeave(object sender, EventArgs e)
        {
            this.SetHighlighted(false);
        }

        private void txtAuthors_TextChanged(object sender, EventArgs e)
        {
            TextBox tb = (TextBox)sender;

            using (Graphics g = tb.CreateGraphics())
            {
                //measure the length of the text on the control and re-size to fit
                SizeF textSize = g.MeasureString(tb.Text, tb.Font);

                tb.Size = Size.Ceiling(textSize);
            }

        }

        #endregion

        #region Private Methods

        private void GetFontAndBrushForTileSection(TileSection section, out Font font, out Brush brush)
        {
            Color brushColour = this.lbPublicationTitle.ForeColor;

            if (section.IsTerm)
            {
                //NOTE: section Quartile ranges from 1-4
                brushColour = this.TermQuartileColours[section.Quartile - 1];
            }

            brush = new SolidBrush(brushColour);

            FontStyle style = section.IsTerm ? FontStyle.Bold : FontStyle.Regular;
            font = new Font(this.Font, style);
        }

        private void SetHighlighted(bool highlighted)
        {
            this.plHeader.BackColor = highlighted ? Color.LightBlue : this.BackColor;
        }

        #endregion

        #region Properties

        private PublicationMining Mining
        {
            get { return this._mining; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("Mining");

                this._mining = value;
            }
        }

        private Color[] TermQuartileColours
        {
            get { return this._termQuartileColours; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("TermQuartileColours");

                if (value.Length < 4)
                    throw new ArgumentException("Four quartile colours required");

                this._termQuartileColours = value;
            }
        }

        private bool DetailsVisible
        {
            get { return this._detailsVisible; }
            set
            {
                this._detailsVisible = value;

                if (this._detailsVisible)
                {
                    this.plDisplay.Visible = true;
                    this.Height = this.plDisplay.Height + 5 + this.plHeader.Location.Y + this.plHeader.Height;
                }
                else
                {
                    this.plDisplay.Visible = false;
                    this.Height = this.plHeader.Location.Y + this.plHeader.Height;
                }
            }
        }

        #endregion
    }
}
